#pragma once

#include <iostream>
#include <queue>
#include <unistd.h>

template<class T>
class blockQueue
{
    static const int defaultnum=5;

public:
    //构造函数
    blockQueue(int maxp=defaultnum)
        :_maxp(maxp)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_p_cond,nullptr);
        pthread_cond_init(&_c_cond,nullptr);
    }

    T pop()
    {
        pthread_mutex_lock(&_mutex);
        if(_q.size()==0)
        {
            pthread_cond_wait(&_c_cond,&_mutex);
        }
        
        T out=_q.front();
        _q.pop();
        pthread_cond_signal(&_p_cond);

        pthread_mutex_unlock(&_mutex);

        return out;
    }

    void push(const T &in)
    {
        pthread_mutex_lock(&_mutex);

        if(_q.size()==_maxp)
        {
            pthread_cond_wait(&_p_cond,&_mutex);
        }
        
        _q.push(in);
        pthread_cond_signal(&_c_cond);

        pthread_mutex_unlock(&_mutex);
    }

    //析构函数
    ~blockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_p_cond);
        pthread_cond_destroy(&_c_cond);
    }

private:
    std::queue<T> _q; //生产消费队列
    int _maxp; //最大值
    pthread_mutex_t _mutex; //锁
    pthread_cond_t _p_cond; //生产同步队列
    pthread_cond_t _c_cond; //消费同步队列
};